package com.accounting.client.frontend.product.handlers;

import java.util.ArrayList;
import java.util.List;

import com.accounting.client.ApplicationContext;
import com.accounting.client.frontend.common.MoneyField;
import com.accounting.client.frontend.packages.PackageRow;
import com.accounting.client.remote.Services;
import com.accounting.client.remote.enumeration.Currency;
import com.accounting.client.remote.enumeration.PackageType;
import com.accounting.client.remote.enumeration.StockLocation;
import com.accounting.client.remote.obj.PackageInfo;
import com.accounting.client.remote.obj.PackageItem;
import com.accounting.client.remote.obj.PurchaseRecord;
import com.accounting.client.remote.obj.User;
import com.accounting.client.remote.transfer.AddPackageRequest;
import com.accounting.client.remote.transfer.TransferPurchaseRecordRequest;
import com.accounting.client.resource.BoxResources;
import com.accounting.client.session.ErrorHandler;
import com.accounting.client.session.Session;
import com.accounting.client.session.SessionManager;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;

import corelib.client.CollectionUtil;
import corelib.client.delegate.CompleteCallback;
import corelib.client.delegate.Func1;
import corelib.client.linq.Linq;
import corelib.client.resource.CommonResources;
import corelib.client.schedule.DeferredTask;
import corelib.client.ui.SimpleModal;
import corelib.client.ui.widget.Size;
import corelib.client.ui.widget.WidgetListener;
import corelib.client.ui.widget.WindowHandle;
import corelib.client.ui.widget.button.Button;
import corelib.client.ui.widget.button.IsButton;
import corelib.client.ui.widget.dialog.SimpleDialogHandler;
import corelib.client.ui.widget.form.ImageWidget;
import corelib.client.ui.widget.form.IntSelectBox;
import corelib.client.ui.widget.form.SelectField;
import corelib.client.ui.widget.form.SimpleLabel;
import corelib.client.ui.widget.form.fomatters.ValueFormatter;
import corelib.client.ui.widget.layout.LabelAlignment;
import corelib.client.ui.widget.layout.RelativeColumn;
import corelib.client.ui.widget.layout.RelativeLayout;
import corelib.client.ui.widget.layout.RelativeRow;
import corelib.client.ui.widget.messagebox.SimpleMessageBox;

public class TransferPurchaseHandler extends SimpleDialogHandler {

	private MoneyField   costField;
	private MoneyField   postageField;
	private IntSelectBox countField;
	private SelectField<StockLocation> locationField;
	private SelectField<User> posterField;
	
	private ImageWidget addPackageIcon;

	private RelativeColumn packagePanel;
	private RelativeColumn buttonGroups;

	private PurchaseRecord purchaseRecord;
	private final List<PackageRow> stockPackages = new ArrayList<PackageRow>();

	public TransferPurchaseHandler(PurchaseRecord record) {
		this.purchaseRecord = record;
		this.packagePanel = new RelativeColumn();
		this.buttonGroups = new RelativeColumn();
	}

	@Override
	public String getHeading() {
		return "转移库存信息";
	}

	@Override
	public Size getSize() {
		return new Size(1200, 800);
	}

	@Override
	public Widget getContentPanel() {
		FlowPanel panel = new FlowPanel();
		panel.getElement().getStyle().setPadding(20, Unit.PX);

		RelativeColumn column = new RelativeColumn();
		int lw = 100;
		int fw = 150;

		addPackageIcon = new ImageWidget(BoxResources.INSTANCE.plus16(),
			new Size(16, 16), new WidgetListener() {
				@Override
				public void valueUpdated(Widget widget) {
					PackageRow row = new PackageRow(stockPackages);
					stockPackages.add(row);
					packagePanel.addRow(row);
				}
			}
		);

		countField   = new IntSelectBox(1, purchaseRecord.getCount());
		costField    = new MoneyField(Currency.AUD);
		postageField = new MoneyField(Currency.AUD);
		postageField.setValueEnable(true);
		postageField.getValueField().setDouble(0.0, false);
		locationField = new SelectField<StockLocation>(StockLocation.All,
			new WidgetListener() {
				@Override
				public void valueUpdated(Widget widget) {
					if (locationField.getSelectedOption() == null 
					 || locationField.getSelectedOption().getLocation() == StockLocation.Sydney.getLocation()){
						postageField.getValueField().setDouble(0.0, false);
						postageField.setEnable(false);
						addPackageIcon.setEnabled(false);
						packagePanel.clear();
					}
					else {
						postageField.setEnable(true);
						addPackageIcon.setEnabled(true);
					}
				}
			}
		);
		locationField.setNullable(true);
		locationField.setOptionFormatter("请选择目标库存位置",new ValueFormatter<StockLocation>() {
			@Override
			public String format(StockLocation value) {
				return value.getCname();
			}
		});
		
		
		posterField = new SelectField<User>(ApplicationContext.getAllUsers());
		posterField.setNullable(true);
		posterField.setOptionFormatter("请选择转库操作员.",new ValueFormatter<User>(){
			@Override
			public String format(User value) {
				return value.getCName();
			}
		});
		posterField.setSelectedOption(ApplicationContext.getUser(Session.Current.getUserId()));
		
		RelativeRow row = column.addRow();
		row.add(new SimpleLabel(" ").setBold(true), new SimpleLabel(
				purchaseRecord.getProductName()).setBold(true), RelativeLayout
				.create(200, LabelAlignment.Top, lw));
		RelativeLayout layoutData = RelativeLayout.create(fw,
				LabelAlignment.Top, lw);
		row.add(new SimpleLabel("数量").setBold(true), countField, layoutData);
		row.addSpace(12);
		row.add(new SimpleLabel("单件购买成本").setBold(true),
				costField.getValueField(), layoutData);
		row.addSpace(12);
		row.add(new SimpleLabel("单件邮费").setBold(true),
				postageField.getValueField(), layoutData);
		row.addSpace(12);
		row.add(new SimpleLabel("目标库存位置").setBold(true), locationField,
				layoutData);
		row.addSpace(12);
		row.add(new SimpleLabel("转库操作员").setBold(true), posterField,
				layoutData);
		row.addSpace(12);
		row.add(new SimpleLabel(""), addPackageIcon, layoutData);

		Button submitBtn = new Button("递交",
				CommonResources.INSTANCE.accept16(), new WidgetListener() {
					@Override
					public void valueUpdated(Widget widget) {
						update();
					}
				});

		this.buttonGroups.addRow().addSpace(200).add(submitBtn, 100);
		this.packagePanel.setRowSpacing(10);
		
		bind();

		column.setRowSpacing(12);
		column.addRow().add(packagePanel);
		column.addRow().add(buttonGroups);
		panel.add(column.getPanel());
		return panel;
	}

	@Override
	public IsButton[] getButtons() {
		return new IsButton[0];
	}

	@Override
	public void onClosing(WindowHandle windowHandle) {
		windowHandle.close();
	}

	@Override
	public void onShowing() {
		super.onShowing();
		if (this.purchaseRecord.getLocation() == StockLocation.Sydney
				.getLocation()) {
			return;
		}
		new DeferredTask().run(new ScheduledCommand() {
			@Override
			public void execute() {
				String passport = SessionManager.getPassport();
				Services.PackageService.ListPackagesByReference(passport,
						purchaseRecord.getId(),
						new AsyncCallback<List<PackageInfo>>() {
							@Override
							public void onFailure(Throwable caught) {
								ErrorHandler.handleServiceError(caught);
							}

							@Override
							public void onSuccess(List<PackageInfo> result) {
								for (PackageInfo packageInfo : result) {
									PackageRow row = new PackageRow(
											stockPackages);
									row.setItem(packageInfo);
									stockPackages.add(row);
									packagePanel.addRow(row);
								}
							}
						});
			}
		}, 400);
	}

	private List<PackageItem> getPackageItems() {
		return Linq.select(stockPackages, new Func1<PackageRow, PackageItem>() {
			@Override
			public PackageItem run(PackageRow param) {
				return param.getItem();
			}
		});
	}

	private void bind() {
		this.locationField.setSelectedOption(StockLocation.China);
		this.costField.getValueField().setDouble(purchaseRecord.getCost(),false);
		this.countField.setSelectedOption(purchaseRecord.getCount(), false);
		this.postageField.getValueField().setEnabled(true);
		this.postageField.getValueField().setDouble(purchaseRecord.getPostage(), false);
	}

	private void update() {
		if (postageField.getValue() == 0.0) {
			postageField.getValueField().markError("转运邮费不能为零");
			return;
		}
		
		if (locationField.getSelectedOption() != StockLocation.China){
			locationField.markError("库存位置必须为中国");
			return;
		}
		
		if (posterField.getSelectedOption() == null){
			posterField.markError("请选择转库操作员");
			return;
		}
		
		final List<PackageItem> packages = getPackageItems();
		if (CollectionUtil.isEmpty(packages)) {
			SimpleMessageBox.error("错误", "请点击绿色加号添加转运包裹信息", CompleteCallback.Nil);
			return;
		}

		for (PackageRow packageItem : stockPackages) {
			if (packageItem.validate() == Boolean.FALSE) {
				return;
			}
		}

		TransferPurchaseRecordRequest request = new TransferPurchaseRecordRequest();
		request.setId(purchaseRecord.getId());
		request.setCount(countField.getInteger());
		request.setPostage(postageField.getValue());
		request.setLocation(this.locationField.getSelectedOption().getLocation());
		request.setOperatorId(posterField.getSelectedOption().getUserId());
		
		final String passport = SessionManager.getPassport();
		SimpleModal.show("设置转运购买记录...");
		Services.ProductService.TransferPurchaseRecord(passport, request,
			new AsyncCallback<String>() {
				@Override
				public void onFailure(Throwable caught) {
					SimpleModal.hide();
					ErrorHandler.handleServiceError(caught);
				}
				
				@Override
				public void onSuccess(String result) {
					SimpleModal.hide();
					if (!CollectionUtil.isEmpty(packages)) {
						for (PackageItem packageItem : packages) {
							 packageItem.setReference(result);
							 packageItem.setShippingAddress(locationField.getSelectedOption().getCname());
							 packageItem.setType(PackageType.Stock.getType());
							 packageItem.setDescription(purchaseRecord.getProductName() + " " +countField.getInteger());
						}
						AddPackageRequest request = new AddPackageRequest();
						request.setPackageItems(packages);
						Services.PackageService.AddPackage(passport, request, new AsyncCallback<Boolean>() {
							@Override
							public void onFailure(Throwable caught) {
								ErrorHandler.handleServiceError(caught);
							}
							
							@Override
							public void onSuccess(Boolean result) {
								if (result == Boolean.TRUE) {
									closeDialog();
								}
							}
						});
					}
				}
			}
		);
	}
}
